/**
 *  ZMessage.js
 *  author xyang create by 2021/7/1
 *
 *  实现: 该文件导出一个构造函数, 意味着 ZMessage() 是可执行的,会产生一个Message变量,
 *  该变量存放在ZMessage静态变量中, 静态变量是全局唯一的, 模仿 Element UI (Message)
 *
 *
 *  使用方法:
 *  import ZMessage from './plugins/z-message/ZMessage'
 *
 *  自定义配置项
 *  ZMessage.setConfig({ max: 1, isQueue: true, showNewest: true })
 *
 *  覆盖默认$message
 *  Vue.prototype.$message = ZMessage
 *  100% 兼容Element message, 额外新增了 overall 属性,  会覆盖之前的全部属性
 *
 */
import { Message } from 'element-ui'

const messageTypes = ['success', 'warning', 'error', 'info']

function ZMessage (options) {
  if (!(this instanceof ZMessage)) {
    return new ZMessage(options)
  }

  this.init(options)
}

ZMessage.queue = [] // 未展示数据的消息队列

ZMessage.instances = [] // 消息体实例列表

// 配置项
ZMessage.config = {

  max: 0, // 最大显示数

  isQueue: false, // 是否以队列形式存储为展示消息

  showNewest: true // 是否后添加的消息覆盖前面的消息

}

// 配置参数

ZMessage.setConfig = function (config = {}) {
  ZMessage.config = { ...ZMessage.config, ...config }
}

ZMessage.close = Message.close

ZMessage.closeAll = Message.closeAll

// 各消息类型静态方法

messageTypes.forEach(type => {
  ZMessage[type] = options => {
    let opts = options

    if (typeof options === 'string') {
      opts = {

        message: options

      }
    }

    return new ZMessage({ ...opts, type })
  }
})

// 初始化
ZMessage.prototype.init = function (options) {
  const { max, isQueue, showNewest } = ZMessage.config

  // 判断如果超出最大消息数时，删除消息
  if (max > 0 && ZMessage.instances.length >= max && showNewest && !isQueue) {
    this.removeMessages()
  }

  // 传入了覆盖全部属性,  关闭全部消息
  if (options.overall) {
    ZMessage.closeAll()

    // 清空所有队列消息
    ZMessage.queue = []
  }

  if (ZMessage.instances.length >= max && isQueue) {
    // 添加队列元素
    ZMessage.queue.push(this.saveToQueue(options))
  } else if (ZMessage.instances.length < max || !max) {
    // TODO 当max大于1时, 可能会消息重叠
    this.setMessage(options)
  }
}

// 移除消息
ZMessage.prototype.removeMessages = function () {
  const {
    instances,
    config: { max }
  } = ZMessage

  ZMessage.instances = instances.filter((instance, index) => {
    if (index < instances.length - max + 1) {
      instance && instance.close()

      return false
    }

    return true
  })
}

// 获取消息实例和添加事件监听
ZMessage.prototype.setMessage = function (options) {
  const instance = Message(options)

  // 监听消息消失事件，从实例列表移除当前消息实例
  instance.$watch('visible', val => {
    ZMessage.instances = ZMessage.instances.filter(item => item !== instance)
    if (ZMessage.config.isQueue && ZMessage.queue.length) {
      // 取出一个队列元素运行
      ZMessage.queue.shift()()
    }
  })

  ZMessage.instances.push(instance)
}

// 生成队列元素，延迟执行
ZMessage.prototype.saveToQueue = function (options) {
  return () => {
    this.setMessage(options)
  }
}

export default ZMessage
